﻿using System;
using System.Drawing;
using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using ImageProcessor.Shared;
using ImageProcessor.Shared.ImageExtensions;
using Color = System.Drawing.Color;

namespace ImageProcessor.Tim
{
    public class ColorFilterVM : ImageProcessorBaseVM
    {
        public static readonly DependencyProperty ColorFilterProperty =
            DependencyProperty.Register("ColorFilter", typeof (ColorFilterTypes), typeof (ColorFilterVM), new PropertyMetadata(default(ColorFilterTypes)){PropertyChangedCallback = ColorFilterPropertyChanged});

        public static readonly DependencyProperty IsGrayscaleProperty =
            DependencyProperty.Register("IsGrayscale", typeof (bool), typeof (ColorFilterVM), new PropertyMetadata(default(bool)) { PropertyChangedCallback = IsGrayscalePropertyChanged});

        private static void IsGrayscalePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            ((ColorFilterVM) d).IsGrayscaleChanged();
        }

        private static void ColorFilterPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            ((ColorFilterVM) d).ColorFilterChanged();
        }

        public ColorFilterVM(MainViewModel mainVM) : base(mainVM)
        {
        }

        private ImageSource _resultImage;

        public ImageSource ResultImage
        {
            get { return _resultImage; }
            private set
            {
                if (_resultImage == value)
                    return;
                _resultImage = value;
                OnPropertyChanged("ResultImage");
            }
        }

        public ColorFilterTypes ColorFilter
        {
            get { return (ColorFilterTypes)GetValue(ColorFilterProperty); }
            set { SetValue(ColorFilterProperty, value); }
        }
        
        public bool IsGrayscale
        {
            get { return (bool)GetValue(IsGrayscaleProperty); }
            set { SetValue(IsGrayscaleProperty, value); }
        }

        private void ColorFilterChanged()
        {
            ResultImage = SetColorFilter(((BitmapSource) MainVM.SourceImage).BitmapSourceToBitmap(), ColorFilter).BitmapToBitmapSource();
        }

        private void IsGrayscaleChanged()
        {
            var bitmapSourceToBitmap = ((BitmapSource) MainVM.SourceImage).BitmapSourceToBitmap();
            if (IsGrayscale)
            {
                ResultImage = SetGrayscale(bitmapSourceToBitmap).BitmapToBitmapSource();
            }
            else
                ResultImage = SetColorFilter(bitmapSourceToBitmap, ColorFilter).BitmapToBitmapSource();
        }

        public Bitmap SetColorFilter(Bitmap bmap, ColorFilterTypes colorFilterType)
        {
            if (colorFilterType == ColorFilterTypes.None)
            {
                return bmap;
            }

            Color c;
            for (int i = 0; i < bmap.Width; i++)
            {
                for (int j = 0; j < bmap.Height; j++)
                {
                    c = bmap.GetPixel(i, j);
                    int nPixelR = 0;
                    int nPixelG = 0;
                    int nPixelB = 0;
                    if (colorFilterType == ColorFilterTypes.Red)
                    {
                        nPixelR = c.R;
                        nPixelG = c.G - 255;
                        nPixelB = c.B - 255;
                    }
                    else if (colorFilterType == ColorFilterTypes.Green)
                    {
                        nPixelR = c.R - 255;
                        nPixelG = c.G;
                        nPixelB = c.B - 255;
                    }
                    else if (colorFilterType == ColorFilterTypes.Blue)
                    {
                        nPixelR = c.R - 255;
                        nPixelG = c.G - 255;
                        nPixelB = c.B;
                    }
                    
                    nPixelR = Math.Max(nPixelR, 0);
                    nPixelR = Math.Min(255, nPixelR);

                    nPixelG = Math.Max(nPixelG, 0);
                    nPixelG = Math.Min(255, nPixelG);

                    nPixelB = Math.Max(nPixelB, 0);
                    nPixelB = Math.Min(255, nPixelB);

                    bmap.SetPixel(i, j, Color.FromArgb((byte)nPixelR,
                      (byte)nPixelG, (byte)nPixelB));
                }
            }
            return bmap;
        }

        public Bitmap SetGrayscale(Bitmap bmap)
        {
            Color c;
            for (int i = 0; i < bmap.Width; i++)
            {
                for (int j = 0; j < bmap.Height; j++)
                {
                    c = bmap.GetPixel(i, j);
                    byte gray = (byte)(.299 * c.R + .587 * c.G + .114 * c.B);

                    bmap.SetPixel(i, j, Color.FromArgb(gray, gray, gray));
                }
            }
            return bmap;
        }
    }
}